//
//  CHStringAdditions.m
//  Chocolat
//
//  Created by Pieter Omvlee on 8/10/08.
//  Copyright 2008 Insearchofaname. All rights reserved.
//

#import "CHStringAdditions.h"

static NSTextStorage *textStorage;

@implementation NSString (CHStringAdditions)
- (float)heightWithFont:(NSFont *)myFont maxWidth:(float)myWidth
{
  NSTextContainer *textContainer = nil;
  NSLayoutManager *layoutManager = nil;
  
  if (!textStorage) {
    textStorage     = [[NSTextStorage alloc] initWithString:self];
    textContainer = [[[NSTextContainer alloc] initWithContainerSize:NSMakeSize(myWidth, FLT_MAX)] autorelease];
    layoutManager = [[[NSLayoutManager alloc] init] autorelease];
    
    [layoutManager addTextContainer:textContainer];
    [textStorage addLayoutManager:layoutManager];
    [textContainer setLineFragmentPadding:0.0];
    [layoutManager setTypesetterBehavior:NSTypesetterBehavior_10_2_WithCompatibility];
  } else {
    [textStorage replaceCharactersInRange:NSMakeRange(0, [textStorage length]) withString:self];
    
    layoutManager = [[textStorage layoutManagers] firstObject];
    textContainer = [[layoutManager textContainers] firstObject];
    
    [textContainer setContainerSize:NSMakeSize(myWidth, FLT_MAX)];
  }
//  [layoutManager setHyphenationFactor:1.0];
  [textStorage addAttribute:NSFontAttributeName value:myFont range:NSMakeRange(0, [textStorage length])];
  
  (void) [layoutManager glyphRangeForTextContainer:textContainer];
  return [layoutManager usedRectForTextContainer:textContainer].size.height;
}

- (int)fontSizeToFitStringWithAttributes:(CHStringAttributes *)attributes inSize:(NSSize)aSize
{
  return [self fontSizeToFitStringWithAttributes:attributes inSize:aSize maximumFontSize:256];
}

- (int)fontSizeToFitStringWithAttributes:(CHStringAttributes *)attributes inWidth:(int)width
{
  return [self fontSizeToFitStringWithAttributes:attributes inSize:NSMakeSize(width, FLT_MAX)];
}

- (int)fontSizeToFitStringWithAttributes:(CHStringAttributes *)attributes inHeight:(int)height
{
  return [self fontSizeToFitStringWithAttributes:attributes inSize:NSMakeSize(FLT_MAX, height)];
}

- (void)fitStringAttributes:(CHStringAttributes *)attributes inSize:(NSSize)aSize
{
  [attributes setFontSize:[self fontSizeToFitStringWithAttributes:attributes inSize:aSize]];
}

- (void)fitStringAttributes:(CHStringAttributes *)attributes inWidth:(int)width
{
  [attributes setFontSize:[self fontSizeToFitStringWithAttributes:attributes inWidth:width]];
}

- (void)fitStringAttributes:(CHStringAttributes *)attributes inHeight:(int)height
{
  [attributes setFontSize:[self fontSizeToFitStringWithAttributes:attributes inHeight:height]];
}

- (int)fontSizeToFitStringWithAttributes:(CHStringAttributes *)attributes inSize:(NSSize)max maximumFontSize:(int)maxSize;
{
  NSSize s       = NSZeroSize;
  int chosenSize = [attributes fontSize];
  
  while (s.width < max.width && s.height < max.height && chosenSize < maxSize) {
    [attributes setFontSize:chosenSize];
    s = [self sizeWithAttributes:attributes];
    
    if (s.width < max.width && s.height < max.height)
      chosenSize++;
  }
  return chosenSize-1;
}

- (BOOL)containsSubstring:(NSString *)sub
{
  return [self rangeOfString:sub].location != NSNotFound;
}

- (NSArray *)words
{
  NSCharacterSet *spaces = [NSCharacterSet characterSetWithCharactersInString:@"- "];
  NSArray *words = [[self componentsSeparatedByCharactersInSet:spaces] map:@selector(stringByTrimmingCharactersInSet:)
                                                                withObject:[NSCharacterSet whitespaceCharacterSet]];
  
  NSMutableArray *split = [NSMutableArray array];
  NSCharacterSet *upper  = [NSCharacterSet uppercaseLetterCharacterSet];
  
  for (NSString *word in words) {
    //if there are caps in here, we split those as too.
    int i = 0;
    int from = 0;
    for (i=0; i<[word length]; i++) {
      if (i != 0 && [upper characterIsMember:[word characterAtIndex:i]]) {
        [split addObject:[word substringWithRange:NSMakeRange(from, i-from)]];
        from = i;
      }
    }
    [split addObject:[word substringWithRange:NSMakeRange(from, [word length]-from)]];
  }
  
  //a third run will put all the one-character strings in one word
  NSMutableArray *result = [NSMutableArray array];
  
  NSString *previous = nil;
  for (NSString *word in split) {
    if ([word length] > 1) {
      [result addObjectIfNotNil:previous];
      [result addObject:word];
      previous = nil;
    }
    else {
      if (previous)
        previous = [previous stringByAppendingString:word];
      else
        previous = word;
    }
  }
  
  [result addObjectIfNotNil:previous];
  
  return result;
    
//  NSMutableArray *result = [NSMutableArray array];
//  
//  //1: split spaces
//  NSArray *words = [self componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"- "]];
//  for (NSString *word in words) {
//    NSScanner *scanner = [NSScanner scannerWithString:word];
//    
//    while(![scanner isAtEnd]) {
//      NSString *newWord;
//      if ([scanner scanUpToCharactersFromSet:[NSCharacterSet uppercaseLetterCharacterSet] intoString:&newWord])
//        [result addObject:newWord];
//      else
//        [scanner setScanLocation:[scanner scanLocation] + 1];
//    }
//  }
//  return result;
}

@end

@implementation NSAttributedString (CHAttributedStringAdditions)
- (float)heightWithFont:(NSFont *)myFont maxWidth:(float)myWidth
{
  return [[self string] heightWithFont:myFont maxWidth:myWidth];
}
@end
